package pe.edu.upc.e41a.javasoft.daoImpl;

import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import pe.edu.upc.e41a.javasoft.dao.UsuarioDao;
import pe.edu.upc.e41a.javasoft.domain.Aviso;
import pe.edu.upc.e41a.javasoft.domain.Publicacion;
import pe.edu.upc.e41a.javasoft.domain.TipoDocumento;
import pe.edu.upc.e41a.javasoft.domain.TipoPersona;
import pe.edu.upc.e41a.javasoft.domain.Transaccion;
import pe.edu.upc.e41a.javasoft.domain.Usuario;


@Repository(value = "UsuarioDao")
public class UsuarioDaoImpl implements UsuarioDao {
	
	private static final Log log = LogFactory.getLog(AvisoDaoImpl.class);

	@PersistenceContext
	transient EntityManager em;

	public final EntityManager entityManager() {
		EntityManager entityManager = em;
		if (entityManager == null)
			throw new IllegalStateException(
					"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
		return entityManager;
	}

	@Transactional
	@Override
	public void saveUsuario(Usuario usuario) {
		if (em == null)
			this.em = this.em;
		em.persist(usuario);
		
	}

	@Transactional
	@Override
	public void updateUsuario(Usuario usuario) {
		if (em == null)
			this.em = this.em;
		em.merge(usuario);
		em.flush();
		
	}

	@Transactional
	@Override
	public void deleteUsuario(Usuario usuario) {
		if (em == null)
			this.em = this.em;
		if (em.contains(usuario)) {
			em.remove(usuario);
		} else {
			Usuario attached = this.findUsuario(usuario.getCodigo());
			em.remove(attached);
	}
		
	}
	
	// Finders comunes

	@Override
	public  long countUsuarios() {
        return em.createQuery("SELECT COUNT(o) FROM Usuario o", Long.class).getSingleResult();
    }

	@Override
	public  List<Usuario> findAllUsuarios() {
        return em.createQuery("SELECT o FROM Usuario o", Usuario.class).getResultList();
    }

	@Override
	public  Usuario findUsuario(Integer codigo) {
        if (codigo == null) return null;
        return em.find(Usuario.class, codigo);
    }

	@Override
	public  List<Usuario> findUsuarioEntries(int firstResult, int maxResults) {
        return em.createQuery("SELECT o FROM Usuario o", Usuario.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }
	
	
	// Finders avanzados
	@Override
	public  TypedQuery<Usuario> findUsuariosByApellidoMaternoEquals(String apellidoMaterno) {
        if (apellidoMaterno == null || apellidoMaterno.length() == 0) throw new IllegalArgumentException("The apellidoMaterno argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoMaterno = :apellidoMaterno", Usuario.class);
        q.setParameter("apellidoMaterno", apellidoMaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoMaternoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoMaterno IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoMaternoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoMaterno IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoMaternoLike(String apellidoMaterno) {
        if (apellidoMaterno == null || apellidoMaterno.length() == 0) throw new IllegalArgumentException("The apellidoMaterno argument is required");
        apellidoMaterno = apellidoMaterno.replace('*', '%');
        if (apellidoMaterno.charAt(0) != '%') {
            apellidoMaterno = "%" + apellidoMaterno;
        }
        if (apellidoMaterno.charAt(apellidoMaterno.length() - 1) != '%') {
            apellidoMaterno = apellidoMaterno + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.apellidoMaterno) LIKE LOWER(:apellidoMaterno)", Usuario.class);
        q.setParameter("apellidoMaterno", apellidoMaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoMaternoNotEquals(String apellidoMaterno) {
        if (apellidoMaterno == null || apellidoMaterno.length() == 0) throw new IllegalArgumentException("The apellidoMaterno argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoMaterno != :apellidoMaterno", Usuario.class);
        q.setParameter("apellidoMaterno", apellidoMaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoPaternoEquals(String apellidoPaterno) {
        if (apellidoPaterno == null || apellidoPaterno.length() == 0) throw new IllegalArgumentException("The apellidoPaterno argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoPaterno = :apellidoPaterno", Usuario.class);
        q.setParameter("apellidoPaterno", apellidoPaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoPaternoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoPaterno IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoPaternoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoPaterno IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoPaternoLike(String apellidoPaterno) {
        if (apellidoPaterno == null || apellidoPaterno.length() == 0) throw new IllegalArgumentException("The apellidoPaterno argument is required");
        apellidoPaterno = apellidoPaterno.replace('*', '%');
        if (apellidoPaterno.charAt(0) != '%') {
            apellidoPaterno = "%" + apellidoPaterno;
        }
        if (apellidoPaterno.charAt(apellidoPaterno.length() - 1) != '%') {
            apellidoPaterno = apellidoPaterno + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.apellidoPaterno) LIKE LOWER(:apellidoPaterno)", Usuario.class);
        q.setParameter("apellidoPaterno", apellidoPaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByApellidoPaternoNotEquals(String apellidoPaterno) {
        if (apellidoPaterno == null || apellidoPaterno.length() == 0) throw new IllegalArgumentException("The apellidoPaterno argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.apellidoPaterno != :apellidoPaterno", Usuario.class);
        q.setParameter("apellidoPaterno", apellidoPaterno);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByAvisoes(Set<Aviso> avisoes) {
        if (avisoes == null) throw new IllegalArgumentException("The avisoes argument is required");
        
        StringBuilder queryBuilder = new StringBuilder("SELECT o FROM Usuario AS o WHERE");
        for (int i = 0; i < avisoes.size(); i++) {
            if (i > 0) queryBuilder.append(" AND");
            queryBuilder.append(" :avisoes_item").append(i).append(" MEMBER OF o.avisoes");
        }
        TypedQuery<Usuario> q = em.createQuery(queryBuilder.toString(), Usuario.class);
        int avisoesIndex = 0;
        for (Aviso _aviso: avisoes) {
            q.setParameter("avisoes_item" + avisoesIndex++, _aviso);
        }
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByClaveEquals(String clave) {
        if (clave == null || clave.length() == 0) throw new IllegalArgumentException("The clave argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.clave = :clave", Usuario.class);
        q.setParameter("clave", clave);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByClaveIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.clave IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByClaveIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.clave IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByClaveLike(String clave) {
        if (clave == null || clave.length() == 0) throw new IllegalArgumentException("The clave argument is required");
        clave = clave.replace('*', '%');
        if (clave.charAt(0) != '%') {
            clave = "%" + clave;
        }
        if (clave.charAt(clave.length() - 1) != '%') {
            clave = clave + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.clave) LIKE LOWER(:clave)", Usuario.class);
        q.setParameter("clave", clave);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByClaveNotEquals(String clave) {
        if (clave == null || clave.length() == 0) throw new IllegalArgumentException("The clave argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.clave != :clave", Usuario.class);
        q.setParameter("clave", clave);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByCorreoEquals(String correo) {
        if (correo == null || correo.length() == 0) throw new IllegalArgumentException("The correo argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.correo = :correo", Usuario.class);
        q.setParameter("correo", correo);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByCorreoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.correo IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByCorreoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.correo IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByCorreoLike(String correo) {
        if (correo == null || correo.length() == 0) throw new IllegalArgumentException("The correo argument is required");
        correo = correo.replace('*', '%');
        if (correo.charAt(0) != '%') {
            correo = "%" + correo;
        }
        if (correo.charAt(correo.length() - 1) != '%') {
            correo = correo + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.correo) LIKE LOWER(:correo)", Usuario.class);
        q.setParameter("correo", correo);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByCorreoNotEquals(String correo) {
        if (correo == null || correo.length() == 0) throw new IllegalArgumentException("The correo argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.correo != :correo", Usuario.class);
        q.setParameter("correo", correo);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoBetween(Date minFechaNacimiento, Date maxFechaNacimiento) {
        if (minFechaNacimiento == null) throw new IllegalArgumentException("The minFechaNacimiento argument is required");
        if (maxFechaNacimiento == null) throw new IllegalArgumentException("The maxFechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento BETWEEN :minFechaNacimiento AND :maxFechaNacimiento", Usuario.class);
        q.setParameter("minFechaNacimiento", minFechaNacimiento);
        q.setParameter("maxFechaNacimiento", maxFechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoEquals(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento = :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoGreaterThan(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento > :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoGreaterThanEquals(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento >= :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoLessThan(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento < :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoLessThanEquals(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento <= :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByFechaNacimientoNotEquals(Date fechaNacimiento) {
        if (fechaNacimiento == null) throw new IllegalArgumentException("The fechaNacimiento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.fechaNacimiento != :fechaNacimiento", Usuario.class);
        q.setParameter("fechaNacimiento", fechaNacimiento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNombresEquals(String nombres) {
        if (nombres == null || nombres.length() == 0) throw new IllegalArgumentException("The nombres argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.nombres = :nombres", Usuario.class);
        q.setParameter("nombres", nombres);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNombresIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.nombres IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNombresIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.nombres IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNombresLike(String nombres) {
        if (nombres == null || nombres.length() == 0) throw new IllegalArgumentException("The nombres argument is required");
        nombres = nombres.replace('*', '%');
        if (nombres.charAt(0) != '%') {
            nombres = "%" + nombres;
        }
        if (nombres.charAt(nombres.length() - 1) != '%') {
            nombres = nombres + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.nombres) LIKE LOWER(:nombres)", Usuario.class);
        q.setParameter("nombres", nombres);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNombresNotEquals(String nombres) {
        if (nombres == null || nombres.length() == 0) throw new IllegalArgumentException("The nombres argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.nombres != :nombres", Usuario.class);
        q.setParameter("nombres", nombres);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNumeroDocumentoEquals(String numeroDocumento) {
        if (numeroDocumento == null || numeroDocumento.length() == 0) throw new IllegalArgumentException("The numeroDocumento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.numeroDocumento = :numeroDocumento", Usuario.class);
        q.setParameter("numeroDocumento", numeroDocumento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNumeroDocumentoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.numeroDocumento IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNumeroDocumentoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.numeroDocumento IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNumeroDocumentoLike(String numeroDocumento) {
        if (numeroDocumento == null || numeroDocumento.length() == 0) throw new IllegalArgumentException("The numeroDocumento argument is required");
        numeroDocumento = numeroDocumento.replace('*', '%');
        if (numeroDocumento.charAt(0) != '%') {
            numeroDocumento = "%" + numeroDocumento;
        }
        if (numeroDocumento.charAt(numeroDocumento.length() - 1) != '%') {
            numeroDocumento = numeroDocumento + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.numeroDocumento) LIKE LOWER(:numeroDocumento)", Usuario.class);
        q.setParameter("numeroDocumento", numeroDocumento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByNumeroDocumentoNotEquals(String numeroDocumento) {
        if (numeroDocumento == null || numeroDocumento.length() == 0) throw new IllegalArgumentException("The numeroDocumento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.numeroDocumento != :numeroDocumento", Usuario.class);
        q.setParameter("numeroDocumento", numeroDocumento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByPublicacions(Set<Publicacion> publicacions) {
        if (publicacions == null) throw new IllegalArgumentException("The publicacions argument is required");
        
        StringBuilder queryBuilder = new StringBuilder("SELECT o FROM Usuario AS o WHERE");
        for (int i = 0; i < publicacions.size(); i++) {
            if (i > 0) queryBuilder.append(" AND");
            queryBuilder.append(" :publicacions_item").append(i).append(" MEMBER OF o.publicacions");
        }
        TypedQuery<Usuario> q = em.createQuery(queryBuilder.toString(), Usuario.class);
        int publicacionsIndex = 0;
        for (Publicacion _publicacion: publicacions) {
            q.setParameter("publicacions_item" + publicacionsIndex++, _publicacion);
        }
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosBySexo(Character sexo) {
        if (sexo == null) throw new IllegalArgumentException("The sexo argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.sexo = :sexo", Usuario.class);
        q.setParameter("sexo", sexo);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTelefonoEquals(String telefono) {
        if (telefono == null || telefono.length() == 0) throw new IllegalArgumentException("The telefono argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.telefono = :telefono", Usuario.class);
        q.setParameter("telefono", telefono);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTelefonoIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.telefono IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTelefonoIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.telefono IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTelefonoLike(String telefono) {
        if (telefono == null || telefono.length() == 0) throw new IllegalArgumentException("The telefono argument is required");
        telefono = telefono.replace('*', '%');
        if (telefono.charAt(0) != '%') {
            telefono = "%" + telefono;
        }
        if (telefono.charAt(telefono.length() - 1) != '%') {
            telefono = telefono + "%";
        }
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.telefono) LIKE LOWER(:telefono)", Usuario.class);
        q.setParameter("telefono", telefono);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTelefonoNotEquals(String telefono) {
        if (telefono == null || telefono.length() == 0) throw new IllegalArgumentException("The telefono argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.telefono != :telefono", Usuario.class);
        q.setParameter("telefono", telefono);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTipoDocumento(TipoDocumento tipoDocumento) {
        if (tipoDocumento == null) throw new IllegalArgumentException("The tipoDocumento argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.tipoDocumento = :tipoDocumento", Usuario.class);
        q.setParameter("tipoDocumento", tipoDocumento);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTipoPersona(TipoPersona tipoPersona) {
        if (tipoPersona == null) throw new IllegalArgumentException("The tipoPersona argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.tipoPersona = :tipoPersona", Usuario.class);
        q.setParameter("tipoPersona", tipoPersona);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByTransaccions(Set<Transaccion> transaccions) {
        if (transaccions == null) throw new IllegalArgumentException("The transaccions argument is required");
        
        StringBuilder queryBuilder = new StringBuilder("SELECT o FROM Usuario AS o WHERE");
        for (int i = 0; i < transaccions.size(); i++) {
            if (i > 0) queryBuilder.append(" AND");
            queryBuilder.append(" :transaccions_item").append(i).append(" MEMBER OF o.transaccions");
        }
        TypedQuery<Usuario> q = em.createQuery(queryBuilder.toString(), Usuario.class);
        int transaccionsIndex = 0;
        for (Transaccion _transaccion: transaccions) {
            q.setParameter("transaccions_item" + transaccionsIndex++, _transaccion);
        }
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByUsuarioEquals(String usuario) {
        if (usuario == null || usuario.length() == 0) throw new IllegalArgumentException("The usuario argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.usuario = :usuario", Usuario.class);
        q.setParameter("usuario", usuario);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByUsuarioIsNotNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.usuario IS NOT NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByUsuarioIsNull() {
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.usuario IS NULL", Usuario.class);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByUsuarioLike(String usuario) {
        if (usuario == null || usuario.length() == 0) throw new IllegalArgumentException("The usuario argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE LOWER(o.usuario) LIKE LOWER(:usuario)", Usuario.class);
        q.setParameter("usuario", usuario);
        return q;
    }
    
	@Override
    public  TypedQuery<Usuario> findUsuariosByUsuarioNotEquals(String usuario) {
        if (usuario == null || usuario.length() == 0) throw new IllegalArgumentException("The usuario argument is required");
        
        TypedQuery<Usuario> q = em.createQuery("SELECT o FROM Usuario AS o WHERE o.usuario != :usuario", Usuario.class);
        q.setParameter("usuario", usuario);
        return q;
    }

}
